package com.ddkj.netty.server.socket.basisServer;

import com.alibaba.fastjson.JSONObject;
import com.ddkj.netty.Setting;
import com.ddkj.netty.comm.JSONDateFormat;
import com.ddkj.netty.comm.JsonUtil;
import com.ddkj.netty.comm.ResultCodeEnum;
import com.ddkj.netty.redis.RedisUtil;
import com.ddkj.netty.server.TCPAddress;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.AttributeKey;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.HashMap;
import java.util.Map;

/**
 * TCPByteHandler
 */
public class SocketBasisHandler extends SimpleChannelInboundHandler<String> {

    private static final Log log = LogFactory.getLog(SocketBasisHandler.class);

    //会话
    public static final AttributeKey<TCPAddress> KEY = AttributeKey.valueOf(Setting.SOCKET_DDKJ_NETTY);

    //存储channel
    public static Map<String, Channel> channelMap = new HashMap<>();

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {

        TCPAddress tcpAddress = new TCPAddress(ctx.channel());

        log.info(Setting.BASIS_SERVER_NAME + "client_ip--> " + tcpAddress.getClientIP() + " 【上线】");

        ctx.channel().attr(KEY).set(tcpAddress);
        //存储channel
        channelMap.put(tcpAddress.getClientIP(), ctx.channel());

        //向后台服务器返回数据
        String data = JSONObject.toJSONString(JsonUtil.getResultJson(ResultCodeEnum.ONLINE));
        ctx.channel().writeAndFlush(data);
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String s) throws Exception {

        //返回数据
        String data = null;

        //获取用户数据
        TCPAddress tcpAddress = ctx.channel().attr(KEY).get();
        String clientIP = tcpAddress.getClientIP();//ip

        //读取数据
        log.info(Setting.BASIS_SERVER_NAME + "client_ip--> " + clientIP + " 【数据】" + s);

        if (tcpAddress == null || clientIP == null) {
            data = JSONObject.toJSONString(JsonUtil.getFailJsonObject("服务器存储地址错误"));
            ctx.channel().writeAndFlush(data);
        }

        JSONDateFormat jsonDateFormat = JSONObject.parseObject(s, JSONDateFormat.class);
        if (jsonDateFormat == null) {
            //参数校验
            data = JSONObject.toJSONString(JsonUtil.getFailJsonObject("参数错误"));
            ctx.channel().write(new TextWebSocketFrame(data));
        }

        String sender = jsonDateFormat.getSender();//发送者
        String recipient = jsonDateFormat.getRecipient();//消费者

        if ((sender == null && recipient == null) || StringUtils.isBlank(sender)) {
            //参数校验
            data = JSONObject.toJSONString(JsonUtil.getFailJsonObject("参数错误"));
            ctx.channel().writeAndFlush(data);
        }

        //进行存储判断
        String rSen = RedisUtil.get(Setting.DDKJ_NETTY_SOCKET_HEADER + sender);
        log.info("----SOCKET 客户端--( sender " + sender + " )--(  ip " + rSen + ")--(clientIP " + clientIP + ")");
        if (rSen == null || !rSen.equals(clientIP)) {

            //删除老的ip
            if (rSen != null && !rSen.equals(clientIP)) {
                RedisUtil.remove(Setting.DDKJ_NETTY_SOCKET_HEADER + rSen);
            }

            //存储数据,清缓存时所用
            RedisUtil.set(Setting.DDKJ_NETTY_SOCKET_HEADER + sender, clientIP);
            RedisUtil.set(clientIP, Setting.DDKJ_NETTY_SOCKET_HEADER + sender);
        }

        if (recipient == null || StringUtils.isBlank(recipient)) {
            //业务处理器登陆后，不需要继续进行
            return;
        }

        //缓存获取接收者
        String recip = RedisUtil.get(Setting.DDKJ_NETTY_SOCKET_HEADER + recipient);
        if (recip == null) {
            JSONObject jsonObject = JSONObject.parseObject(s);
            jsonObject.put("code", ResultCodeEnum.FAIL.getValue());
            jsonObject.put("msg", "接收者错误");
            jsonObject.remove("data");
            ctx.channel().writeAndFlush(jsonObject.toJSONString());
            log.info("----SOCKET 客户端--( 接受者错误 )--目标为--" + recipient);
            return;
        }

        //获取接收者Channel
        Channel getChannel = channelMap.get(recip);
        if (getChannel != null && getChannel.isActive()) {
            JSONObject jsonObject = JSONObject.parseObject(s);
            jsonObject.put("code", 202);
            jsonObject.put("msg", "receive");
            //发送消息
            getChannel.writeAndFlush(jsonObject.toJSONString());
        } else {
            JSONObject jsonObject = JSONObject.parseObject(s);
            jsonObject.put("code", ResultCodeEnum.FAIL.getValue());
            jsonObject.put("msg", "客户端未在线");
            jsonObject.remove("data");
            ctx.channel().writeAndFlush(jsonObject.toJSONString());
            log.info("----SOCKET 客户端--( 客户端未在线 )--客户端id为--" + recip);
            return;
        }

        //向后台服务器返回数据
        JSONObject jsonObject = JSONObject.parseObject(s);
        jsonObject.put("code", ResultCodeEnum.SUCCESS.getValue());
        jsonObject.put("msg", ResultCodeEnum.SUCCESS.getKey());
        jsonObject.remove("data");
        ctx.channel().writeAndFlush(jsonObject.toJSONString());
        return;

    }

    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        TCPAddress tcpAddress = new TCPAddress(ctx.channel());
        String clientIP = tcpAddress.getClientIP();
        removeIP(clientIP);
        log.info(Setting.BASIS_SERVER_NAME + "client_ip--> " + clientIP + " 【下线】");
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {

        log.error("异常消息为-------->" + cause);
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        log.info("什么鬼<userEventTriggered>------>" + evt);
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        super.channelReadComplete(ctx);
        ctx.flush();
    }


    //清除数据
    protected void removeIP(String ipURI) {

        String whos = RedisUtil.get(ipURI);

        if (whos != null) {
            RedisUtil.remove(whos);
        }
        RedisUtil.remove(ipURI);
        //清空存储Map
        channelMap.remove(ipURI);

    }


}
